package controllers

import (
	"encoding/json"
	"fmt"
	"github.com/goravel/framework/contracts/database/orm"
	"github.com/goravel/framework/contracts/http"
	"github.com/goravel/framework/facades"
	httpfacade "github.com/hulutech-web/http_result"
	"github.com/samber/lo"
	"github.com/spf13/cast"
	"goravel/app/http/controllers/common"
	"goravel/app/http/requests"
	"goravel/app/models"
	"goravel/packages/socket/servers"
)

type RepairController struct {
	//Dependent services
}

func NewRepairController() *RepairController {
	return &RepairController{
		//Inject services
	}
}

// Index 用户分页查询，支持搜索，路由参数?name=xxx&pageSize=1&currentPage=1&sort=xxx&order=xxx,等其他任意的查询参数
// @Summary      用户分页查询
// @Description  用户分页查询
// @Tags         RepairController
// @Accept       json
// @Produce      json
// @Id RepairIndex
// @Security ApiKeyAuth
// @Param Authorization header string false "Bearer 用户令牌"
// @Param  pageSize  query  string  false  "pageSize"
// @Param  currentPage  query  string  false  "currentPage"
// @Param  sort  query  string  false  "sort"
// @Param  order  query  string  false  "order"
// @Success 200 {string} json {}
// @Router       /api/admin/repair [get]
func (r *RepairController) Index(ctx http.Context) http.Response {
	types := []models.Repair{}
	queries := ctx.Request().Queries()
	res, err := httpfacade.NewResult(ctx).SearchByParams(queries, nil).
		ResultPagination(&types, "Ticket", "Car", "Ticket.Users", "Ticket.Kind", "Ticket.Services", "Ticket.Processes", "Records")
	if err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "", err.Error())
	}
	return res
}

// Online 在线工单，该工单为启示状态尚未被接单
// @Summary      用户分页查询
// @Description  用户分页查询
// @Tags         RepairController
// @Accept       json
// @Produce      json
// @Id RepairOnline
// @Security ApiKeyAuth
// @Param Authorization header string false "Bearer 用户令牌"
// @Param  pageSize  query  string  false  "pageSize"
// @Param  currentPage  query  string  false  "currentPage"
// @Param  sort  query  string  false  "sort"
// @Param  order  query  string  false  "order"
// @Success 200 {string} json {}
// @Router       /api/admin/repair/online [get]
func (r *RepairController) Online(ctx http.Context) http.Response {
	types := []models.Repair{}
	queries := ctx.Request().Queries()
	res, err := httpfacade.NewResult(ctx).SearchByParams(queries, map[string]interface{}{
		"state": 0,
	}).ResultPagination(&types, "Car")
	if err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "", err.Error())
	}
	return res
}

// Show 查看部门.
// @Summary Show department
// @Description 查看部门.
// @Tags RepairController
// @Security BearerAuth
// @Accept json
// @Produce json
// @Id RepairShow
// @Param Authorization header string true "Bearer token"
// @Param id path int true "department ID"
// @Success 200 {object} common.SuccessResponse "Successfully retrieved department."
// @Failure 500 {object} common.ErrorResponse "Internal server error."
// @OperationID DepartmentShow
// @Router /api/admin/repair/{id} [get]
func (r *RepairController) Show(ctx http.Context) http.Response {
	id := ctx.Request().RouteInt("id")
	repair := models.Repair{}
	if err := facades.Orm().Query().Model(&models.Repair{}).Where("id=?", id).With("Car").With("Car.Kind").
		Find(&repair); err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "错误", err.Error())
	}
	return httpfacade.NewResult(ctx).Success("", repair)
}

// Store 新增部门.
// @Summary store department
// @Description 新增部门.
// @Tags RepairController
// @Security BearerAuth
// @Accept json
// @Produce json
// @Param departmentData body requests.RepairRequest true "部门数据"
// @Id RepairStore
// @Param Authorization header string true "Bearer token"
// @Success 200 {object} common.SuccessResponse "Successfully retrieved Menus ."
// @Failure 500 {object} common.ErrorResponse "Internal server error."
// @OperationID DepartmentStore
// @Router /api/admin/repair [post]
func (r *RepairController) Store(ctx http.Context) http.Response {
	var repairRequest requests.RepairRequest
	errors, err := ctx.Request().ValidateRequest(&repairRequest)
	if err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "数据错误", err.Error())
	}
	if errors != nil {
		return httpfacade.NewResult(ctx).ValidError("", errors.All())
	}
	user := models.User{}
	facades.Auth(ctx).User(&user)
	repair := models.Repair{
		UserName: repairRequest.UserName,
		Way:      repairRequest.Way,
		Phone:    repairRequest.Phone,
		//时分秒毫秒
		OrderNo:     fmt.Sprintf("MINI-%s", common.GetOrder()),
		UserID:      user.ID,
		Description: repairRequest.Description,
		CarID:       repairRequest.CarID,
		Images:      repairRequest.Images,
		Coordinates: repairRequest.Coordinates,
		Address:     repairRequest.Address,
	}
	err = facades.Orm().Query().Model(&models.Repair{}).Create(&repair)
	//向前端发送一条消息
	users := []models.User{}
	sql := `
			SELECT u.*
			FROM users u
			JOIN role_user ur ON u.id = ur.user_id
			JOIN roles r ON ur.role_id = r.id
			WHERE r.value = 'class_role';`
	facades.Orm().Query().Raw(sql).Scan(&users)

	if err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "数据错误", err.Error())
	}
	return httpfacade.NewResult(ctx).Success("报修成功", nil)
}

// Update 更新部门.
// @Summary update department
// @Description 新增部门.
// @Tags RepairController
// @Security BearerAuth
// @Accept json
// @Produce json
// @Param departmentData body requests.DepartmentRequest true "部门数据"
// @Id RepairUpdate
// @Param Authorization header string true "Bearer token"
// @Param id path int true "department ID"
// @Success 200 {object} common.SuccessResponse "Successfully retrieved Menus ."
// @Failure 500 {object} common.ErrorResponse "Internal server error."
// @OperationID DepartmentUpdate
// @Router /api/admin/repair/{id} [put]
func (r *RepairController) Update(ctx http.Context) http.Response {
	id := ctx.Request().RouteInt("id")
	var repairRequest requests.RepairRequest
	errors, err := ctx.Request().ValidateRequest(&repairRequest)
	if err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "数据错误", err.Error())
	}
	if errors != nil {
		return httpfacade.NewResult(ctx).ValidError("", errors.All())
	}
	var user models.User
	facades.Auth(ctx).User(&user)
	if _, err := facades.Orm().Query().Model(&models.Repair{}).Where("id=?", id).Update(models.Repair{
		UserName:    repairRequest.UserName,
		Way:         repairRequest.Way,
		Phone:       repairRequest.Phone,
		OrderNo:     repairRequest.OrderNo,
		UserID:      user.ID,
		Description: repairRequest.Description,
		CarID:       repairRequest.CarID,
		Images:      repairRequest.Images,
		Coordinates: repairRequest.Coordinates,
		Address:     repairRequest.Address,
	}); err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "更新失败", err.Error())
	}
	return httpfacade.NewResult(ctx).Success("修改成功", nil)
}

// Destroy 删除部门.
// @Summary delete department
// @Description 查看部门.
// @Tags RepairController
// @Security BearerAuth
// @Accept json
// @Produce json
// @Id RepairDestroy
// @Param Authorization header string true "Bearer token"
// @Param id path int true "department ID"
// @Success 200 {object} common.SuccessResponse "Successfully retrieved Menus ."
// @Failure 500 {object} common.ErrorResponse "Internal server error."
// @OperationID RepairDestroy
// @Router /api/admin/repair/{id} [delete]
func (r *RepairController) Destroy(ctx http.Context) http.Response {
	id := ctx.Request().RouteInt("id")
	row, err := facades.Orm().Query().Model(&models.Repair{}).Where("id=?", id).
		Delete(&models.Repair{}, id)
	if err != nil || row.RowsAffected == 0 {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "删除失败", err.Error())
	}
	return httpfacade.NewResult(ctx).Success("删除成功", nil)
}

// List
// @Summary      用户分页查询
// @Description  用户分页查询
// @Tags         RepairController
// @Accept       json
// @Produce      json
// @Id RepairList
// @Security ApiKeyAuth
// @Param Authorization header string false "Bearer 用户令牌"
// @Success 200 {string} json {}
// @Router       /api/admin/repair/list [get]
func (r *RepairController) List(ctx http.Context) http.Response {
	types := []models.Repair{}
	facades.Orm().Query().Model(&models.Repair{}).Find(&types)
	return httpfacade.NewResult(ctx).Success("", types)
}

func (r *RepairController) MiniStore(ctx http.Context) http.Response {
	var repairRequest requests.RepairRequest
	errors, err := ctx.Request().ValidateRequest(&repairRequest)
	if err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "数据错误", err.Error())
	}
	if errors != nil {
		return httpfacade.NewResult(ctx).ValidError("", errors.All())
	}
	user := models.User{}
	facades.Auth(ctx).User(&user)
	//判断用户的角色
	facades.Orm().Query().Model(&models.User{}).Where("id=?", user.ID).With("Roles").Find(&user)
	values := []string{}
	for _, role := range user.Roles {
		values = append(values, role.Value)
	}
	if !lo.Contains(values, "driver") {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "非驾驶员无法开单", nil)
	}
	//carbon.NewDate(carbon.ParseByFormat(storePost.ExpireAt, "2006-01-02"))
	repair := models.Repair{
		UserName: repairRequest.UserName,
		Way:      repairRequest.Way,
		Phone:    repairRequest.Phone,
		//时分秒毫秒
		OrderNo:     fmt.Sprintf("MINI-%s", common.GetOrder()),
		UserID:      user.ID,
		Description: repairRequest.Description,
		CarID:       repairRequest.CarID,
		Images:      repairRequest.Images,
		Coordinates: repairRequest.Coordinates,
		Address:     repairRequest.Address,
	}
	err = facades.Orm().Query().Model(&models.Repair{}).Create(&repair)
	//向前端发送一条消息
	users := []models.User{}
	sql := `
			SELECT u.*
			FROM users u
			JOIN role_user ur ON u.id = ur.user_id
			JOIN roles r ON ur.role_id = r.id
			WHERE r.value = 'class_role';`
	facades.Orm().Query().Raw(sql).Scan(&users)
	//将repair解析为字符串
	repairByte, _ := json.Marshal(repair)
	repairStr := string(repairByte)
	servers.SendMessage2Group("1", cast.ToString(user.ID), "class_role", 5001, "新订单通知", &repairStr)
	if err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "数据错误", err.Error())
	}
	return httpfacade.NewResult(ctx).Success("创建成功", nil)
}

func (r *RepairController) MiniIndex(ctx http.Context) http.Response {
	way := ctx.Request().Query("way")
	user := models.User{}
	facades.Auth(ctx).User(&user)
	db := facades.Orm().Query()
	db.Model(&models.User{}).Where("id=?", user.ID).With("Roles").First(&user)
	values := []string{}
	for _, role := range user.Roles {
		values = append(values, role.Value)
	}

	//如果是维修班长或者维修作业长-全部返回
	if lo.Contains(values, models.CLASS_ROLE) || lo.Contains(values, models.FLOW_ROLE) {
		repairs := []models.Repair{}
		if way == "3" {
			db.Model(&models.Repair{}).WhereNotIn("state", []any{4, 5}).With("Ticket").With("Ticket.Users").
				With("Ticket.Processes").
				With("Ticket.Services").With("Ticket.Parking").Order("id desc").
				Find(&repairs)
			return httpfacade.NewResult(ctx).Success("", repairs)
		}
		db.Model(&models.Repair{}).WhereNotIn("state", []any{4, 5}).With("Ticket").With("Ticket.Users").
			With("Ticket.Processes").
			With("Ticket.Services").With("Ticket.Parking").Order("id desc").
			Where("way=?", way).Find(&repairs)
		return httpfacade.NewResult(ctx).Success("", repairs)
	}

	//如果是维修工，只返回派单给自己的
	if lo.Contains(values, models.EMPLOYEE_ROLE) {
		//1、先通过ticket来判断
		db.Model(&user).With("Tickets").Find(&user)
		tids := []uint{}
		for _, ticket := range user.Tickets {
			tids = append(tids, ticket.ID)
		}
		//已经到达维修环节
		repairs := []models.Repair{}
		tickets := []models.Ticket{}
		if way == "3" {
			db.Model(&models.Ticket{}).Where("id in ?", tids).With("Repair").Find(&tickets)
		} else {
			db.Model(&models.Ticket{}).Where("id in ?", tids).With("Repair", func(query orm.Query) orm.Query {
				return query.Where("way=?", way)
			}).Find(&tickets)
		}

		rids := []uint{}
		for _, ticket := range tickets {
			rids = append(rids, ticket.Repair.ID)
		}
		if way == "3" {
			db.Model(&models.Repair{}).Where("id in ?", rids).WhereNotIn("state", []any{4, 5}).With("Ticket").
				With("Ticket.Users").With("Ticket.Processes").
				With("Ticket.Services").With("Ticket.Parking").Order("id desc").Find(&repairs)
			return httpfacade.NewResult(ctx).Success("", repairs)
		}

		db.Model(&models.Repair{}).Where("id in ?", rids).WhereNotIn("state", []any{4, 5}).Where("way=?", way).With("Ticket").
			With("Ticket.Users").With("Ticket.Processes").
			With("Ticket.Services").With("Ticket.Parking").Order("id desc").Find(&repairs)
		return httpfacade.NewResult(ctx).Success("", repairs)
	}

	//如果是驾驶员
	if lo.Contains(values, models.DRIVER) {
		//已经到达维修环节
		repairs := []models.Repair{}
		if way == "3" {
			db.Model(&models.Repair{}).WhereNotIn("state", []any{4, 5}).With("Ticket").
				With("Ticket.Users").With("Ticket.Processes").
				With("Ticket.Services").With("Ticket.Parking").
				Where("user_id=?", user.ID).Order("id desc").Find(&repairs)
			return httpfacade.NewResult(ctx).Success("", repairs)
		}
		db.Model(&models.Repair{}).WhereNotIn("state", []any{4, 5}).Where("way=?", way).With("Ticket").
			With("Ticket.Users").With("Ticket.Processes").
			With("Ticket.Services").With("Ticket.Parking").
			Where("way=?", way).Where("user_id=?", user.ID).Order("id desc").Find(&repairs)
		return httpfacade.NewResult(ctx).Success("", repairs)
	}
	return httpfacade.NewResult(ctx).Success("", []string{})
}

func (r *RepairController) MiniShow(ctx http.Context) http.Response {
	id := ctx.Request().RouteInt("id")
	repair := models.Repair{}
	if err := facades.Orm().Query().Model(&models.Repair{}).Where("id=?", id).With("Car").With("Car.Kind").
		Find(&repair); err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "错误", err.Error())
	}
	return httpfacade.NewResult(ctx).Success("", repair)
}

func (r *RepairController) MiniHistoryIndex(ctx http.Context) http.Response {
	way := ctx.Request().Query("way")
	user := models.User{}
	facades.Auth(ctx).User(&user)
	db := facades.Orm().Query()
	db.Model(&models.User{}).Where("id=?", user.ID).With("Roles").First(&user)
	values := []string{}
	for _, role := range user.Roles {
		values = append(values, role.Value)
	}

	//如果是维修班长或者维修作业长-全部返回
	if lo.Contains(values, models.CLASS_ROLE) || lo.Contains(values, models.FLOW_ROLE) {
		repairs := []models.Repair{}
		if way == "3" {
			db.Model(&models.Repair{}).WhereIn("state", []any{4, 5}).With("Ticket").With("Ticket.Users").
				With("Ticket.Processes").
				With("Ticket.Services").With("Ticket.Parking").Order("id desc").
				Find(&repairs)
			return httpfacade.NewResult(ctx).Success("", repairs)
		}
		db.Model(&models.Repair{}).WhereIn("state", []any{4, 5}).With("Ticket").With("Ticket.Users").
			With("Ticket.Processes").
			With("Ticket.Services").With("Ticket.Parking").
			Where("way=?", way).Order("id desc").Find(&repairs)
		return httpfacade.NewResult(ctx).Success("", repairs)
	}

	//如果是维修工，只返回派单给自己的
	if lo.Contains(values, models.EMPLOYEE_ROLE) {
		//1、先通过ticket来判断
		db.Model(&user).With("Tickets").Find(&user)
		tids := []uint{}
		for _, ticket := range user.Tickets {
			tids = append(tids, ticket.ID)
		}
		//已经到达维修环节
		repairs := []models.Repair{}
		tickets := []models.Ticket{}
		if way == "3" {
			db.Model(&models.Ticket{}).Where("id in ?", tids).With("Repair").Order("id desc").Find(&tickets)
		} else {
			db.Model(&models.Ticket{}).Where("id in ?", tids).With("Repair", func(query orm.Query) orm.Query {
				return query.Where("way=?", way)
			}).Order("id desc").Find(&tickets)
		}

		rids := []uint{}
		for _, ticket := range tickets {
			rids = append(rids, ticket.Repair.ID)
		}
		if way == "3" {
			db.Model(&models.Repair{}).Where("id in ?", rids).WhereIn("state", []any{4, 5}).With("Ticket").
				With("Ticket.Users").With("Ticket.Processes").
				With("Ticket.Services").With("Ticket.Parking").Order("id desc").Find(&repairs)
			return httpfacade.NewResult(ctx).Success("", repairs)
		}

		db.Model(&models.Repair{}).Where("id in ?", rids).WhereIn("state", []any{4, 5}).Where("way=?", way).With("Ticket").
			With("Ticket.Users").With("Ticket.Processes").
			With("Ticket.Services").With("Ticket.Parking").Order("id desc").Find(&repairs)
		return httpfacade.NewResult(ctx).Success("", repairs)
	}

	//如果是驾驶员
	if lo.Contains(values, models.DRIVER) {
		//已经到达维修环节
		repairs := []models.Repair{}
		if way == "3" {
			db.Model(&models.Repair{}).WhereIn("state", []any{4, 5}).With("Ticket").
				With("Ticket.Users").With("Ticket.Processes").
				With("Ticket.Services").With("Ticket.Parking").
				Where("user_id=?", user.ID).Order("id desc").Find(&repairs)
			return httpfacade.NewResult(ctx).Success("", repairs)
		}
		db.Model(&models.Repair{}).WhereIn("state", []any{4, 5}).Where("way=?", way).With("Ticket").
			With("Ticket.Users").With("Ticket.Processes").
			With("Ticket.Services").With("Ticket.Parking").
			Where("way=?", way).Where("user_id=?", user.ID).Order("id desc").Find(&repairs)
		return httpfacade.NewResult(ctx).Success("", repairs)
	}
	return httpfacade.NewResult(ctx).Success("", []string{})
}
